package server_logic;

import java.io.IOException;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import java.util.Iterator;

import mysqlCnnection.ConnectionTOmysql;
import mysqlCnnection.IlegalMySQLPasswordORUserNameException;
import mysqlCnnection.LogInCheck;
import Gui.ServerInitialize;
import Gui.StartForm;
import ocsf.server.AbstractServer;
import ocsf.server.ConnectionToClient;

/**
 * This class overrides some of the methods in the abstract 
 * superclass in order to give more functionality to the server.
 */
public class Server_Main_Class extends AbstractServer 
{
	
	
	private Vector<Object[]> clientsVec =new Vector<Object[]>();
	 final public static int DEFAULT_PORT = 5555;
	 //Constructors ****************************************************
	  /**
	   * Constructs an instance of the Server_Main_Class.
	   *
	   * @param port The port number to connect on.
	   */
	  public Server_Main_Class(int port) 
	  {
		 super(port);
	  }
	  
	//Instance methods ************************************************
	  
	  /**
	   * 
	   */
	  private synchronized boolean isAlreadyLogIn(String username, String password, 
			  ConnectionToClient client)
	  {
		  int size = clientsVec.size();
		  boolean loginflasg = false;
		  int clienttoclose = -1;
		  Object[] clientinfo = null;
		  int i=0;
		  Thread[] clientThreadList = getClientConnections();
		  for (i=0; i < size; i++)
		  {
			  clientinfo = clientsVec.get(i);
			 if (clientinfo[0].equals(password) || clientinfo[1].equals(username))
			 {
				    for (int j=0; j < clientThreadList.length; j++)
				    {
				    	try
				    	{
				    		if (((ConnectionToClient)clientThreadList[j]).getId() == (Long)clientinfo[3])
				    	    {
				    			if (((ConnectionToClient)clientThreadList[j]).isAlive())
				    			{
				    				//System.out.println("ALIVE");
				    				loginflasg = true;
				    			}
				    			else
				    				clienttoclose = j;			    			
				    			break;
				    	    }				    		
				        }
				        catch (Exception ex) 
				        {
				        	clienttoclose = j;
				        	break;
				        }
				    }
				    break;					    
		     }
	      }
		  if (loginflasg)
		  {
			  try
			    {
			    	client.sendToClient("AlreadyIN");	
			    	return true;
			    }catch(IOException ioxception)
			    {
			    	return true;
			    }
		  }
		  else
		  	  if (i < size) 
		  		 clientsVec.removeElementAt(i);
		  if (clienttoclose > -1)
		  {
			  try 
			  {
				((ConnectionToClient)clientThreadList[clienttoclose]).close();
			  } 
			  catch (IOException e) 
			  {
				
			  }			 
		  }
		  return false;
	  }
	  
	  /**
	   * 
	   * @param username
	   * @param password
	   * @param client
	   * @return
	   */
	  private synchronized boolean ifToAddToclientsVec(String username, String password, 
			  ConnectionToClient client)
	  {
		  String strmsg=null;
		  try
			{
				LogInCheck logincheck = new LogInCheck();
				strmsg = logincheck.passwordAndUserNameCheck(username, password);
			}catch (IlegalMySQLPasswordORUserNameException except)
		    {
				   	
		    }
			
			try 
			{
				client.sendToClient(strmsg);
				if (strmsg != null && !strmsg.equals("Ilegalusername"))
				{
					return true;					
				}
				return false;
			}
			catch (Exception e) 
			{
				return false;
			}		  
	  } 
	  
	  /**
	   * 
	   * @param username
	   * @param password
	   * @param client
	   */
	  private synchronized void aAddToclientsVec(String username, String password, 
			  ConnectionToClient client)
	  {
		 Object[] clientinfo = new Object[4];
		 clientinfo[0] = password;
		            clientinfo[1] = username;
		                       clientinfo[2] = client.getInetAddress();
		                                  clientinfo[3] = client.getId();
		                                  clientsVec.add(clientinfo);	                                  
	  }
	  
	  /**
	   * This method logOf the client from the system
	   * @param username
	   * @param password
	   * @param client
	   */
	  private synchronized void logOF( ConnectionToClient client)
	  {
		  Object[] clientinfo = new Object[4];
			for (Iterator<Object[]> it = clientsVec.iterator(); it.hasNext();)
			{
				clientinfo = (Object[])it.next();
				if (clientinfo[3].equals(client.getId()))
				{
					it.remove();
					try 
					{
						client.sendToClient("LoggedOF");
						client.close();						
					} catch (IOException e) 
					{
						
					}
					return;
				}				
			}		  
	  }
	  
	  /*
	   * synchronized public void clientDisconnected(
			    ConnectionToClient client) 
	  */
	  /**
	   * This method handles any messages received from the client.
	   *
	   * @param msg The message received from the client.
	   * @param client The connection from which the message originated.
	   */
	  public synchronized void handleMessageFromClient
	    (Object msg, ConnectionToClient client)
	  {
		  String[] str = null;
		  str = (String[])msg;
		  if (str[0].equals("Login"))
		  {
			  if (isAlreadyLogIn(str[1] , str[2], client))
			  {
				  return;
			  }
			  if (ifToAddToclientsVec(str[1] , str[2], client))
			  {
				  aAddToclientsVec(str[1] , str[2], client);
			  }
			  return;
		  }
		  else
			  if (str[0].equals("logOF"))
			  {
				  System.out.println(str[0]);
				  logOF(client);
				  return;
			  }
		  try
		    {
		    	ConnectionToUser conntoclient = new ConnectionToUser((String[])msg);
		    	client.sendToClient(conntoclient.getMessageToClient());		    	
		    }catch(IOException ioxception)
		    {
		    	 System.out.println("ERROR to send message : " + msg + " to " + client);
		    }
		    catch(Exception e)
		    {
		    	System.out.println("ERROR!!!");
		    }    
	 }
	  
	  
	  
	  public void clientConnected(ConnectionToClient client) 
	  {
		   Thread[] clientThreadList = getClientConnections();

		    for (int i=0; i<clientThreadList.length; i++)
		    {
		      try
		      {
		    	  System.out.println(((ConnectionToClient)clientThreadList[i]).getInetAddress());
		    	  System.out.println(((ConnectionToClient)clientThreadList[i]).getId());		    	 
		      }
		      catch (Exception ex) 
		      {
		    	 
		      }
		    }
		    System.out.println("********************");
		    
		    Object[] clientinfo = new Object[4];
			for (Iterator<Object[]> it = clientsVec.iterator(); it.hasNext();)
			{
				clientinfo = (Object[])it.next();
				System.out.println(clientinfo[0].toString()+clientinfo[1].toString()
						+clientinfo[2].toString()+clientinfo[3].toString());				
			}
			System.out.println("######################");
		    
	  }
	  
	  public synchronized void clientDisconnected(ConnectionToClient client) 
	  {
		  System.out.println("clientDisconnected:"+" ID: "+client.getId()+" Name: "+client.getName()); 
	  } 

	  /**
	   * This method overrides the one in the superclass.  Called
	   * when the server starts listening for connections.
	   */
	  protected void serverStarted()
	  {
	    System.out.println
	      ("Server listening for connections on port " + getPort());
	  }
	  
	  /**
	   * This method overrides the one in the superclass.  Called
	   * when the server stops listening for connections.
	   */
	  protected void serverStopped()
	  {
	    System.out.println
	      ("Server has stopped listening for connections.");
	  }
	  
	  //Class methods ***************************************************
	  
	  /**
	   * This method is responsible for the creation of 
	   * the server instance (there is no UI in this phase).
	   *
	   * @param args[0] The port number to listen on.  Defaults to 5555 
	   *          if no argument is entered.
	   */
	  public static void main(String[] args) 
	  {
	    
	    final ServerInitialize server_initialize = new ServerInitialize();
	    
	    server_initialize.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
	    server_initialize.setSize( 400, 300 ); // set frame size
	        
	    server_initialize.getStartButton().addActionListener(new java.awt.event.ActionListener() 
		{
			public void actionPerformed(java.awt.event.ActionEvent e) 
			{	
				 int port = 0; //Port to listen on
				 try
				    {
				     	port = server_initialize.getPort(); //Get port from command line
				     	if (port == -1 || port < 0)
				     	{
				     		JOptionPane.showMessageDialog(null, "Ilegal port number");
				     		port = DEFAULT_PORT; //Set port to 5555
				     	}
				     	if (port == 0)
				     		port = DEFAULT_PORT; //Set port to 5555			     		
				    }
				    catch(Throwable t)
				    {
				    	port = DEFAULT_PORT; //Set port to 5555
				    }
				    char[] char_password = server_initialize.getMySQLpassword();
				    int len = char_password.length;
				    String password = "";
				    for (int i=0; i < len; i++)
				    	password = password+char_password[i];
				    ConnectionTOmysql.setPassword(password);
				    ConnectionTOmysql.setUsername(server_initialize.getMySQLuserName());
				    Server_Main_Class s_m_c = new Server_Main_Class(port);
				    try 
				    {	
				    	ConnectionTOmysql connectiontomysql = new ConnectionTOmysql();
				    	s_m_c.listen(); //Start listening for connections
				    	StartForm startform = new StartForm(port);
				    	server_initialize.setContentPane(startform);				    							
				    }
				    catch (IlegalMySQLPasswordORUserNameException except)
				    {
				    	JOptionPane.showMessageDialog(null, "ERROR - Ilegal My SQL usermane or password!");				    	
				    }
				    catch (Exception ex) 
				    {
				    	JOptionPane.showMessageDialog(null, "ERROR - Could not listen for clients!");						
				    }				    
			}
		});	    
	    server_initialize.setVisible( true ); // display frame	   
	  }
	}
	//End of Server_Main_Class class
	